'use strict';
(function($) {
    /**
     *
     * @param options array: max_level=int,最高层级; data_parse=function,数据格式化; data=object,数据,优先级高于source_url;source_url=远程获取数据url;
     * @constructor
     */
    function ScrollSelect(options) {
        var defaultOptions = {
            max_level: 3,
            id_key: 'id',
            name_key: 'name',
            children_key: 'children',
            data_parser: function(data) {
                return data;
            }
        };

        options = $.extend(defaultOptions, options);
        this.domNode = null;
        this.maxLevel = options.max_level;
        this.dataParser = options.data_parser;
        this.idKey = options.id_key;
        this.nameKey = options.name_key;
        this.childrenKey = options.children_key;
        this.data = options.data;
        this.source_url = options.source_url;
        this.initialized = false;
        this.onSelect = options.on_select;
        this.init();
    }
    ScrollSelect.prototype.init = function () {
        if(this.initialized) {
            return;
        }
        var selectInstance = this;
        if(!this.data && !this.source_url) {
            throw 'You must give "data" or "source_url".';
        }
        if(!this.data && this.source_url) {
            $.get(this.source_url, function(remoteData) {
                selectInstance.data = selectInstance.dataParser.apply(selectInstance, [remoteData]);
                selectInstance.initialized = true;
            });
        }else {
            selectInstance.data = selectInstance.dataParser.apply(selectInstance, [selectInstance.data]);
            selectInstance.initialized = true;
        }
    };
    /**
     * show select
     * @param targetElement 若指定element参数，弹框会在指定节点位置正下方弹出
     */
    ScrollSelect.prototype.show = function (targetElement) {
        var selectInstance = this;
        this.targetElement = targetElement;
        targetElement = $(targetElement);
        var top = targetElement.top || $(targetElement).offset().top + $(targetElement).outerHeight();
        var left = targetElement.left || $(targetElement).offset().left;
        if(!this.domNode) {
            //
            var $cp = $('<div class="scroll-select-container"><div class="panel"><ul class="menu"></ul></div></div>');
            this.data.forEach(function(item, index) {
                var $li = $('<li><span></span></li>')
                    .data('index', index).data('id', item[selectInstance.idKey]);
                if(item[selectInstance.childrenKey]) {
                    $li.addClass('has-sub');
                }
                $li.children('span').text(item[selectInstance.nameKey]);
                $cp.find('.menu').append($li);
            });
            $cp.on('mouseenter', 'li', function (event) {
                var $li = $(this);
                $li.closest('.panel').nextAll().remove();
                $li.siblings().removeClass('active');
                $li.addClass('active');
                if(!$li.hasClass('has-sub')) {
                    //没有下级数据
                    return;
                }
                var currentList = selectInstance.data;
                $li.closest('.panel').prevAll().find('li.active').each(function () {
                    currentList = currentList[$(this).index()][selectInstance.childrenKey];
                });
                var currentData = currentList[$li.index()];
                var $panel = $('<div class="panel"><ul class="menu"></ul></div>');
                if(!currentData[selectInstance.childrenKey]) {
                    return;
                }
                var nextLevel = $li.closest('.panel').index() + 1;
                currentData[selectInstance.childrenKey].forEach(function(item, index) {
                    var $liAppend = $('<li><span></span></li>')
                        .data('index', index).data('id', item[selectInstance.idKey]);
                    $liAppend.children('span').text(item[selectInstance.nameKey]);
                    if(nextLevel + 1 < selectInstance.maxLevel && item[selectInstance.childrenKey]) {
                        $liAppend.addClass('has-sub');
                    }
                    $panel.find('.menu').append($liAppend);
                });

                $cp.append($panel);
            }).on('click','li', function(event) {
                var $li = $(this);
                var level = $li.closest('.panel').index() + 1;
                var currentList = selectInstance.data;
                var selectedDatas = [];
                $li.closest('.panel').prevAll().find('li.active').each(function () {
                    selectedDatas.push(currentList[$(this).index()]);
                    currentList = currentList[$(this).index()][selectInstance.childrenKey];
                });
                var selectedData = currentList[$li.index()];
                selectedDatas.push(selectedData);
                if(typeof selectInstance.onSelect === 'function') {
                    selectInstance.onSelect.apply(selectInstance, [selectedDatas, level, selectInstance.targetElement]);
                }
            });
            this.domNode = $cp[0];
            var handlerName = 'click.scroll_select_hide_'+parseInt((Math.random()*1000000));
            $('body').append(this.domNode);
            setTimeout(function(){
                selectInstance.hideHandlerName = handlerName;
                $('body').on(handlerName, function(event) {
                    var $targetCp = $(event.target).closest('.scroll-select-container');
                    if($targetCp.length===0 || $targetCp[0]!==$cp[0]) {
                        $cp.remove();
                        $('body').off(handlerName);
                        selectInstance.domNode = null;
                        selectInstance.hideHandlerName = "";
                    }
                });
            },100);
        }
        $(this.domNode).offset({top:top,left:left});
    };
    ScrollSelect.prototype.hide = function() {
        if(this.domNode) {
            $('body').trigger(this.hideHandlerName).off(this.hideHanlderName);
        }
    };
    window.ScrollSelect = ScrollSelect;
    return ScrollSelect;
})(jQuery);